<!--
 * @Author: your name
 * @Date: 2021-03-15 20:53:56
 * @LastEditTime: 2021-03-15 20:56:17
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edi
 * @FilePath: \study\js\面试题\数组计算.html
-->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>

    <body>
        <p>订阅模式</p>
        <button id="box">点击</button>
        <button id="box1">点击1</button>
        <script>
            //            柯里化函数的实现
            // 柯里化函数的定义：将多参数的函数转换成单参数的形式。
            // 柯里化函数实现的原理：利用闭包原理在执行可以形成一个不销毁的作用域，
            // 然后把需要预先处理的内容都储存在这个不销毁的作用域中，并且返回一个最少参数函数。

            // 第一种：固定传入参数，参数够了才执行

            // 复制
            /**
             * 实现要点：柯里化函数接收到足够参数后，就会执行原函数，
             * 那么我们如何去确定何时达到足够的参数呢？
             * 柯里化函数需要记住你已经给过他的参数，如果没给的话，则默认为一个空数组。
             * 接下来每次调用的时候，需要检查参数是否给够，如果够了，
             * 则执行fn，没有的话则返回一个新的 curry 函数，将现有的参数塞给他。
             *
             */
            // 待柯里化处理的函数
            // let sum =  (a, b, c, d) =>{
            //     return a + b + c + d
            // };

            // // 柯里化函数，返回一个被处理过的函数
            // let curry = (fn, ...arr) => {
            //     // arr 记录已有参数
            //     return (...args) => {   // args 接收新参数
            //         if (fn.length <= (...arr,...args)) {  // 参数够时，触发执行
            //             return fn(...arr, ...args)
            //         } else {  // 继续添加参数
            //             return curry(fn, [...arr, ...args])
            //         }
            //     }
            // };

            // var sumPlus = curry(sum);
            // sumPlus(1)(2)(3)(4);
            // sumPlus(1, 2)(3)(4);
            // sumPlus(1, 2, 3)(4);

            // 第二种：不固定传入参数，随时执行

            /**
             * 当然了，柯里化函数的主要作用还是延迟执行，执行的触发条件不一定是参数个数相等，也可以是其他的条件。
             * 例如参数个为0的情况，那么我们需要对上面curry函数稍微做修改
             */
            // 待柯里化处理的函数
            // let sum2 = (arr) => {
            //     return arr.reduce((a, b) => {
            //         return a + b;
            //     });
            // };

            // let curry2 = (fn, ...arr) => {
            //     // arr 记录已有参数
            //     return (...args) => {
            //         // args 接收新参数
            //         if (args.length === 0) {
            //             // 参数为空时，触发执行
            //             return fn(...arr, ...args);
            //         } else {
            //             // 继续添加参数
            //             return curry2(fn, ...arr, ...args);
            //         }
            //     };
            // };

            // var sumPlus2 = curry2(sum2);
            // sumPlus2(1)(2)(3)(4)();
            // sumPlus2(1, 2)(3)(4)();
            // sumPlus2(1, 2, 3)(4)();

            // ------------------------

            let argsSum = (arr) => {
                return arr.reduce((a, b) => {
                    return a + b;
                });
            };

            const foo = (...args1) => {
                const sum1 = argsSum(args1);
                const fn = (...args2) => {
                    const sum2 = argsSum(args2);
                    return foo(sum1 + sum2);
                };
                fn.toString= ()=> {return sum1}
                return fn;
            };
            console.log(Number(foo(1)(2)))
            console.log(Number(foo(1)(2)(3)))
            console.log(Number(foo(1,2)(3)))
        </script>
    </body>
</html>
